NodeGlobal = {
	group : 0,
	node : 1
};

$.widget( "custom.catcomplete", $.ui.autocomplete, {
	_renderMenu: function( ul, items ) {
		var that = this,
		currentCategory = "";
		$.each( items, function( index, item ) {
			if ( item.category != currentCategory ) {
				ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" );
				currentCategory = item.category;
			}
			that._renderItemData( ul, item );
		});
	}
});

/**
 * 给Array对象添加find方法
 * @param e
 * @param identify 对比的对象。如果是对象，要想以'id'或'name'查找，则这里传入'id'/'name'
 * @returns {Number} 元素e所在数组的位置,-1表示没有找到该元素
 */
Array.prototype.find = function(e,identify) {
	if(!identify){
		for ( var i = 0; i < this.length; i++) {
			if (this[i] == e)
				return i;
		}
	}else{
		for ( var i = 0; i < this.length; i++) {
			if (this[i][identify] == e[identify])
				return i;
		}
	}
	return -1;
};

/**
 * 与另一个数组对比
 * @param array
 * @param identify 对比的对象，无则是比较数组元素，有则是比较元素中的某一属性
 * @returns {Array} 第一个数组为本数组特有的，第二个数组为array特有的，第三个数组为公共的本数组元素
 */
Array.prototype.different = function(array,identify){
	var a = new Array();
	var same = new Array();
	for ( var i = 0; i < this.length; i++) {
		var e = this[i];
		var findIndex = array.find(e, 'id');
		findIndex == -1 ? a.push(this[i]):(same.push(this[i]),array.splice(findIndex,1));
	}
	
	return [a,array,same];
};

//重写源代码解决 node.image.alarm的缓存问题 与 只有一种告警颜色的问题
JTopo.Node.prototype.setImage = function (c,d){var e,f;if(null==c)throw new Error("Node.setImage(): 参数Image对象为空!");e=this,"string"==typeof c?(f=null,null==f?(f=new Image,f.src=c,f.onload=function(){1==d&&e.setSize(f.width,f.height);var g=null;g&&(f.alarm=g),e.image=f;}):(d&&this.setSize(f.width,f.height),this.image=f)):(this.image=c,1==d&&this.setSize(c.width,c.height));};
JTopo.Node.prototype.paintAlarmText = function (a){var b,c,d,e;""!=this.alarm&&(a.beginPath(),a.font=this.alarmFont||"10px 微软雅黑",b=a.measureText(this.alarm).width+6,c=a.measureText("田").width+6,d=this.width/2-b/2,e=-this.height/2-c-8,a.strokeStyle=this._c,a.fillStyle=this._c,a.lineCap="round",a.lineWidth=1,a.moveTo(d,e),a.lineTo(d+b,e),a.lineTo(d+b,e+c),a.lineTo(d+b/2+6,e+c),a.lineTo(d+b/2,e+c+8),a.lineTo(d+b/2-6,e+c),a.lineTo(d,e+c),a.lineTo(d,e),a.fill(),a.stroke(),a.closePath(),a.beginPath(),a.strokeStyle="rgba("+this.fontColor+", "+this.alpha+")",a.fillStyle="rgba("+this.fontColor+", "+this.alpha+")",a.fillText(this.alarm,d+2,e+c-4),a.closePath());};
//修改鼠标样式路径找不到的问题
JTopo.MouseCursor.closed_hand = 'url(/webems/static/mouseCur/closedhand.cur) 8 8, default';

MyNode = function(config){
	var c = {};
	if(config.id == null || config.type==null){
		console.log('when init node , id or type required!');
		return null;
	}
	c.id = config.id;
	c.text = config.text || 'node_'+config.id;
	c.x = config.x || 0;
	c.y = config.y || 0 ;
	c.image = config.image || (config.type == NodeGlobal.group)?'/webems/static/modules/topo/images/server-normal.png':'/webems/static/modules/topo/images/wanjet-normal.png';
	c.alarmInfoArr = config.alarmInfoArr || [];
	c.alarmLevelArr = config.alarmLevelArr || [];
	c.type = config.type;
	if(c.type == NodeGlobal.node){//节点只显示名称，网元显示名称与ip
		c.text += '_'+config.ip;
	}
	return c;
};

MyLink = function(config){
	var l = {};
	if(config.fromId == null || config.toId == null){
		return null;
	}
	l.fromId = config.fromId;
	l.toId = config.toId;
	l.alarm = config.alarm;
	return l;
};

TopoUtil = {
	color:['100,100,100','255,0,0','255,204,0','255,255,0','153,0,255'],
	imgSuffix:['offline','critical','major','minor','warning'],
	/**
	 * 设备节点的告警状态
	 * @param node 节点
	 * @param level 告警等级
	 * @param content 最高告警条目数
	 */
	setAlarm : function(node){
		node.alarmLevel = node.alarmLevelArr.length==0?0:node.alarmLevelArr[0];//如果没有，则正常
		node.alarmInfo = node.alarmInfoArr.length==0?null:node.alarmInfoArr[0];//如果没有，则正常
		
		var imgSrcUrl = '';
		if(node.type == NodeGlobal.group){
			imgSrcUrl = 'server';
		}else{
			imgSrcUrl = 'wanjet';
		}
		
		var level = node.alarmLevel;
		switch(level){
			case -1 :
				//node.alarmInfo=null;
				level = 0;//显示offline图片
				break;
			case 0 : 
				node.alarmInfo = null;//显示normal图片，只有设置成null时才会变成normal其它情况则变成相对象的告警状态
				
				break;
			default:
				//其它的level与color,imgSuffix的下标一致
				break;
				
		}
		var _c = 'rgba('+TopoUtil.color[level]+',0.9)';
		node._c = _c;
		imgSrcUrl += '-'+TopoUtil.imgSuffix[level];	
		
		node._tempImgSrcUrl = imgSrcUrl ;
		callbackSetAlarm(node);
		
		
		function callbackSetAlarm(n){
			if(n.image){
				n.image.alarm = $('<img>').attr('src','/webems/static/modules/topo/images/'+n._tempImgSrcUrl+'.png')[0];
				n.alarm = n.alarmInfo;
				return;
			}else{
				setTimeout(function(){
					callbackSetAlarm(n);
				},100);
			}
		}
	}	
};


EmsTopo = function(canvasEle,topoData){
	this.topoId = topoData.id;
	this.topoData = topoData;
	this.background = '/webems/static/modules/topo/images/bg.png';
	this.nodes = new Array();
	this.links = new Array();
	this.stage = new JTopo.Stage(canvasEle);
	this.scene = new JTopo.Scene();
	/**
	 * 初始化
	 */
	this.init = function(){
		showJTopoToobar(this.stage);
		this.scene.background = this.background;
		var _this = this;
		this.scene.mouseup(function(e){_this.contextmenu(e);});
		
		this.stage.add(this.scene);
	};
	
	/**
	 * 根据ID获取节点
	 */
	this.getNodeById = function(nId){
		for(var i=0 ;i<this.nodes.length; i++){
			if(this.nodes[i]._id == nId){
				return this.nodes[i];
			}
		}
		return null;
	};
	
	this.getLinkById = function(lId){
		for(var i=0 ;i<this.links.length; i++){
			if(this.links[i]._id == lId){
				return this.links[i];
			}
		}
		return null;
	};
	
	this.createNode = function(n){
		var exsitNode = this.getNodeById(n.id);
		var node;
		if(exsitNode){
    		node = exsitNode;
    	}else{
    		node = new JTopo.Node(n.text);    		
    	}
		
        node._id = n.id;
        node.setImage(n.image, true);
        node.setLocation(n.x, n.y);
        node.type = n.type;
        node.fontColor = '16,16,16';
        
        //当alarmInfo与alarmLevel变成数组后
        node.alarmInfoArr = n.alarmInfoArr;
        node.alarmLevelArr = n.alarmLevelArr;
        
        var that = this;
        node.dbclick(function(e){
        	var id = this._id;
        	var text = this.text;
        	var type = this.type;
        	
        	that.createTab(type, id, text);
        });
        if(!exsitNode){
        	this.scene.add(node);
        }
        
        //初始化该告警的图片
        this.setAlarm(node);
        
        return node;
    };
    
    this.createTab = function(type, id, text){
    	//节点的双击效果
    	if(type == NodeGlobal.group){
    		/*var tabExist = parent.commonAPI.isExsitTab('subTopo');
        	if(tabExist){
        		var title = $('a[href="#subTopo"]',$(parent.document)).text();
        		var tempTitle = title.replace('节点拓扑(','').replace(')','');
        		if(tempTitle == text){
        			//跳到该页
        			parent.commonAPI.selectTab('subTopo');
        		}else{
        			//关闭该页，再重新打开 
        			var closeSpan = $('a[href="#subTopo"]',$(parent.document)).find('span').eq(0);
            		closeSpan.click();
            		
            		parent.commonAPI.createTab('subTopo','节点拓扑('+text+')','/webems/topo/subTopo/'+id);
        		}
        	}else{
        		parent.commonAPI.createTab('subTopo','节点拓扑('+text+')','/webems/topo/subTopo/'+id);
        	}*/
    		parent.commonAPI.createTab('site_'+id,text,'/webems/topo/subTopo/'+id);
    	}
    	//网元的双击效果
    	else if(type == NodeGlobal.node){
    		/*var tabId = 'neChassis';
    		var tabName = '机架图';
    		var tabExist = parent.commonAPI.isExsitTab(tabId);
        	if(tabExist){
        		var title = $('a[href="#'+tabId+'"]',$(parent.document)).text();
        		var tempTitle = title.replace(tabName+'(','').replace(')','');
        		if(tempTitle == text){
        			//跳到该页
        			parent.commonAPI.selectTab(tabId);
        		}else{
        			//关闭该页，再重新打开 
        			var closeSpan = $('a[href="#'+tabId+'"]',$(parent.document)).find('span').eq(0);
            		closeSpan.click();
            		
            		parent.commonAPI.createTab(tabId,tabName+'('+text+')','/webems/core/index/neChassis?nid='+ id);
        		}
        	}else{
        		parent.commonAPI.createTab(tabId,tabName+'('+text+')','/webems/core/index/neChassis?nid='+ id);
        	}*/
    		parent.commonAPI.createTab('node_'+id,text,'/webems/core/index/neChassis?nid='+ id);
    	}
    };
    
	this.createLink = function(l){
		if(this.getLinkById(l.fromId + '_' + l.toId)){
    		console.log('link exsit!');
    		alert('link exsit!');
    		return;
    	}
		if(this.getLinkById(l.toId + '_' + l.fromId)){
    		console.log('link exsit!');
    		alert('link exsit!');
    		return;
    	}
		
    	var nodeA = this.getNodeById(l.fromId);
    	var nodeZ = this.getNodeById(l.toId);
    	var link = new JTopo.Link(nodeA, nodeZ);
    	link._id = l.fromId + '_' + l.toId;
    	link.strokeColor = '64,64,64';
    	if(l.alarm){
    		link.strokeColor = '255,0,0';
    	}
        link.lineWidth = 1;                
        this.scene.add(link);
        
        link.dbclick(function(e){
        	var fromText = (this.nodeA.text);
        	var toText = (this.nodeZ.text);
        	var fArray = fromText.split('_');
        	var tArray = toText.split('_');
        	var fromName = fromText.replace('_'+fArray[fArray.length-1],'');
        	var toName = toText.replace('_'+tArray[tArray.length-1],'');
        	
        	parent.commonAPI.createTab(this._id,fromName+','+toName,'/webems/topo/topoLink/'+fromName+'/'+toName);
        });
        return link;
    };
    

    /**
     * 外部调用
     */
    this.addNode = function(mynode){
    	//外部调用时，先判断是否存在，如果存在则直接返回
    	
    	var exsitNode = this.getNodeById(mynode.id);
    	if(exsitNode){
    		console.log('node exsited');
    		return;
    	}
    	//若是内部调用，在createNode里判断，如果存在，只是不保存，但更改位置等信息
    	var n = this.createNode(mynode);
    	if(n){
    		this.nodes.push(n);
    	}
    	
    	//刷新父页面的树
    	if(parent.commonAPI){
    		parent.commonAPI.initTree(true);
    	}
    	return n;   	
    };
    
    this.addLink = function(mylink){
    	var l = this.createLink(mylink);
    	if(l){
    		this.links.push(l);
    	}
    	return l;
    };
    
    this.delNodeById = function(id){
    	var n = this.getNodeById(id);
    	var scopeThis = this;
    	if(n.inLinks){
    		n.inLinks.forEach(function(a){scopeThis.delLink(a);});
    	}
    	if(n.outLinks){
    		n.outLinks.forEach(function(a){scopeThis.delLink(a);});
    	}
    	
    	this.scene.remove(n);
    	
    	//为了保证nodes的空间连续性，删除元素后，用最后一个元素来填充
    	var i = this.nodes.find(n);
    	if(i==-1){
    		return;
    	}
    	
    	if(i != (this.nodes.length -1) ){
    		var popnode = this.nodes.pop();
    		this.nodes[i] = popnode;
    	}else{
    		this.nodes.pop();
    	}
    	
    	//刷新父页面树
    	if(parent.commonAPI){
    		parent.commonAPI.initTree(true);
    	}
    };
    
    this.delNode = function(n){
    	this.delNodeById(n._id);
    };
    
    this.delLink = function(l){
    	//this.scene.remove(this.getNodeById(id));  系统已经自动将其删除，
    	//这里将删除缓存
    	//为了保证links的空间连续性，删除元素后，用最后一个元素来填充
    	var i = this.links.find(l);
    	if(i==-1){
    		return;
    	}
    	if(i != (this.links.length -1) ){
    		var poplink = this.links.pop();
    		this.links[i] = poplink;
    	}else{
    		this.links.pop();
    	}
    };
    
    this.delLinkById = function(id){
    	for(var i=0; i<this.links.length; i++){
    		if(this.links[i]._id == id){
    			this.scene.remove(this.links[i]);//因为后续调用会将该link删除，所以先把浏览器的指针删除
    			this.delLink(this.links[i]);
    			break;
    		}
    	}
    	console.log(this.links);
    };
    
    this.setAlarm = function(node){
    	TopoUtil.setAlarm(node);
    };
    
    this.setBackground = function(url){
    	this.background = url;
    	this.scene.setBackground(this.background);
    };
    
    this.contextmenu = function(_e){
    	//这里要将弹出的menu隐藏
    	this.hideMenu();
    	if(_e.button !=2){
    		return;
    	}
    	if(!_e.target){
    		this.showSceneMenu(_e);
    	}else{
    		var e = _e.target;
    		if(e.elementType=='node'){
    			if(e.type == NodeGlobal.group){
        			this.showGroupMenu(_e);
        		}else if(e.type == NodeGlobal.node){
        			this.showNodeMenu(_e);
        		}
    		}else if(e.elementType=='link'){
    			this.showLinkMenu(_e);
    		}
    	}
    	
    };
    
    this.showSceneMenu = function(e){
    	console.log(['请重写EmsTopo.showSceneMenu()方法。这里应该具有添加网元或节点按钮','']);
    };
    
    this.showGroupMenu = function(e){
    	console.log(['请重写EmsTopo.showGroupMenu(n)方法。这里应该具有删除节点/查看节点按钮',e]);
    };
    
    this.showNodeMenu = function(e){
    	console.log(['请重写EmsTopo.showNodeMenu(n)方法。这里应该具有删除网元/查看网元按钮',e]);
    };
    
    this.showLinkMenu = function(e){
    	console.log(['请重写EmsTopo.showLinkMenu(l)方法。这里应该具有删除连接线/查看连接线按钮',e]);
    };
    
    this.hideMenu = function(){
    	console.log('请重写EmsTopo.hideMenu()方法。这里应该隐藏所有的menu。');
    };
    
	this.showTopo = function(_topoData){
		if(_topoData){
			this.topoData = _topoData;
		}
		var topo = this.topoData;
		this.topoId = topo.id;
		var mynodes = topo.nodes;
		var mylinks = topo.links;
		for(var i=0; i<mynodes.length; i++){
			var mynode = this.createNode(mynodes[i]);
			if(mynode){
				this.nodes.push(mynode);
			}
		}
		
		for(var i=0; i<mylinks.length; i++){
			var l = this.createLink(mylinks[i]);
			if(l){
				this.links.push(l);
			}
		}
		
		
		//最后对显示的拓扑图进行修正，从数据库里取出拓扑元素
		
		var that = this;
		$.ajax({
			url:'/webems/topo/getNodesByTopoId',
			data:{id:that.topoId},
			type:'POST',
			success : function(response){
				var list = eval('('+response+')');
				for(var i=0; i<list.length; i++){
					list[i].id = list[i].sid||list[i].nid;
				}
				var differentAndSame = list.different(mynodes, 'id');
				var listOnly = differentAndSame[0];
				var mynodesOnly = differentAndSame[1];
				var same = differentAndSame[2];
				
				//删除mynodesOnly
				for(var i=0; i<mynodesOnly.length; i++){
					that.delNodeById(mynodes[i].id);
				}
				//添加listOnly
				for(var i=0; i<listOnly.length; i++){
					var e = listOnly[i];
					var mynode = new MyNode({ip:e.ip,id:e.id||e.sid||e.nid,text:e.name||e.sname||e.nename,type:that.topoId==0?NodeGlobal.group:NodeGlobal.node,x:0, y:0, alarmLevelArr:e.alarmLevelArr, alarmInfoArr:e.alarmCountArr});
					that.addNode(mynode);
				}
				//更新存在的list的告警信息
				for(var i=0; i<same.length; i++){
					var e = same[i];
					var id = e.id||e.sid||e.nid;
					var nodeTemp = that.getNodeById(id);
					nodeTemp.alarmLevelArr = e.alarmLevelArr;
					nodeTemp.alarmInfoArr = e.alarmCountArr;
					that.setAlarm(nodeTemp);
					if(nodeTemp.type==NodeGlobal.group){
						nodeTemp.text = e.sname;
					}else if(nodeTemp.type==NodeGlobal.node){
						nodeTemp.text = e.nename+'_'+e.ip;
					}
				}
			},
			failure : function(response){
				console.log(response);
			}
		});
		
	};
	
	this.toJson = function(){
		var a = {};
		a.background = this.background;
		a.id = this.topoId;
		a.nodes = new Array();
		a.links = new Array();
		for(var i=0; i<this.nodes.length; i++ ){
			var n = this.nodes[i];
			var mynode = {};
			mynode.id = n._id;
			mynode.text = n.text;
			mynode.image = n.image.src;
			mynode.type = n.type;
			mynode.alarmInfoArr = n.alarmInfoArr;
			mynode.alarmLevelArr = n.alarmLevelArr;
			mynode.x = n.x;
			mynode.y = n.y;
			a.nodes.push(mynode);
		}
		for(var i=0; i<this.links.length; i++ ){
			var l = this.links[i];
			var mylink = {};
			mylink.id = l._id;
			mylink.fromId = l.nodeA._id;
			mylink.toId = l.nodeZ._id;
			mylink.alarm = l.alarm;
			a.links.push(mylink);
		}
		//console.log(JSON.stringify(a));
		return a;
	};
	
	
	this.init();
};


















